package studio.raptor.dispatcher.server.service;

import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import studio.raptor.databus.command.EventMetaData;

/**
 * 幂等性校验，防止消息重复发送
 *
 * @author jack
 * @since 1.0
 */
@Service
public class CacheService {

  private static final Logger log = LoggerFactory.getLogger(CacheService.class);

  @Autowired
  private StringRedisTemplate template;


  /**
   * 检验当前事件是否已经发送给当前渠道
   *
   * @param code 接口编码
   * @param kindId 事件种类id
   * @param eventType 事件类型1：停复机，0：普通业务
   * @param eventMeta 事件元信息
   * @return true:已发送 false：未发送
   */
  @Transactional
  public boolean verify(String code, Integer kindId, Integer eventType, EventMetaData eventMeta) {
    Objects.requireNonNull(code);
    Objects.requireNonNull(kindId);
    Objects.requireNonNull(eventType);
    Objects.requireNonNull(eventMeta);
    String orderId = eventMeta.getBusinessNo();
    log.debug("consumer[{}],verify idempotence event->[{}] ", code, orderId);
    String key = eventType + ":" + kindId + ":" + code + ":" + orderId;
    return template.opsForValue().setIfAbsent(key, String.valueOf(orderId));
  }

  /**
   * 持久化消息体
   */
  public void saveEventBody(String objectKey, Integer kindId, Integer eventType, String body) {
    Objects.requireNonNull(objectKey);
    Objects.requireNonNull(kindId);
    String key = eventType + ":" + kindId + ":" + objectKey;
    template.opsForValue().setIfAbsent(key, body);
  }

  /**
   * 根据事件ID获取事件的消息体
   *
   * @param objectKey 订单id
   * @param kindId 消息主题
   * @return 如果消息存在则返回字符串形式的消息体，如果不存在则返回null
   */
  public String fetchMessageBody(String objectKey, Integer kindId, Integer eventType) {
    Objects.requireNonNull(kindId);
    Objects.requireNonNull(objectKey);
    Objects.requireNonNull(eventType);
    String key = eventType + ":" + kindId + ":" + objectKey;
    return template.opsForValue().get(key);
  }
}
